<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MCP (Model Context Protocol) 演示</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 15px;
            box-shadow: 0 20px 40px rgba(0,0,0,0.1);
            overflow: hidden;
        }
        
        .header {
            background: linear-gradient(45deg, #667eea, #764ba2);
            color: white;
            padding: 30px;
            text-align: center;
        }
        
        .header h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
        }
        
        .header p {
            font-size: 1.1rem;
            opacity: 0.9;
        }
        
        .main-content {
            padding: 30px;
        }
        
        .tabs {
            display: flex;
            background: #f8f9fa;
            border-radius: 10px;
            padding: 5px;
            margin-bottom: 30px;
        }
        
        .tab {
            flex: 1;
            padding: 15px;
            text-align: center;
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.3s ease;
            font-weight: 600;
        }
        
        .tab.active {
            background: #667eea;
            color: white;
        }
        
        .tab-content {
            display: none;
        }
        
        .tab-content.active {
            display: block;
        }
        
        .card {
            background: #f8f9fa;
            border-radius: 10px;
            padding: 20px;
            margin-bottom: 20px;
            border-left: 4px solid #667eea;
        }
        
        .card h3 {
            color: #333;
            margin-bottom: 15px;
        }
        
        .form-group {
            margin-bottom: 20px;
        }
        
        .form-group label {
            display: block;
            margin-bottom: 5px;
            font-weight: 600;
            color: #555;
        }
        
        .form-group input, .form-group textarea, .form-group select {
            width: 100%;
            padding: 12px;
            border: 2px solid #ddd;
            border-radius: 8px;
            font-size: 14px;
            transition: border-color 0.3s ease;
        }
        
        .form-group input:focus, .form-group textarea:focus, .form-group select:focus {
            outline: none;
            border-color: #667eea;
        }
        
        .btn {
            background: #667eea;
            color: white;
            padding: 12px 24px;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-size: 16px;
            font-weight: 600;
            transition: all 0.3s ease;
        }
        
        .btn:hover {
            background: #5a6fd8;
            transform: translateY(-2px);
        }
        
        .result {
            background: #e8f5e8;
            border: 1px solid #4caf50;
            border-radius: 8px;
            padding: 15px;
            margin-top: 15px;
            white-space: pre-wrap;
            font-family: 'Courier New', monospace;
            font-size: 14px;
        }
        
        .error {
            background: #ffe6e6;
            border: 1px solid #f44336;
            color: #d32f2f;
        }
        
        .status {
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 10px 20px;
            border-radius: 25px;
            font-weight: 600;
            z-index: 1000;
        }
        
        .status.connected {
            background: #4caf50;
            color: white;
        }
        
        .status.disconnected {
            background: #f44336;
            color: white;
        }
        
        .capabilities-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 20px;
            margin-top: 20px;
        }
        
        .capability-card {
            background: white;
            border: 2px solid #eee;
            border-radius: 10px;
            padding: 20px;
            transition: all 0.3s ease;
        }
        
        .capability-card:hover {
            border-color: #667eea;
            transform: translateY(-5px);
            box-shadow: 0 10px 20px rgba(0,0,0,0.1);
        }
        
        .capability-title {
            color: #667eea;
            font-size: 1.2rem;
            margin-bottom: 10px;
            display: flex;
            align-items: center;
        }
        
        .capability-title::before {
            content: "🔧";
            margin-right: 10px;
            font-size: 1.5rem;
        }
        
        .capability-card.resource .capability-title::before {
            content: "📂";
        }
        
        .capability-card.prompt .capability-title::before {
            content: "💬";
        }
        
        .notifications {
            position: fixed;
            bottom: 20px;
            right: 20px;
            z-index: 1000;
        }
        
        .notification {
            background: #333;
            color: white;
            padding: 15px 20px;
            border-radius: 10px;
            margin-bottom: 10px;
            min-width: 300px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.3);
            animation: slideIn 0.3s ease;
        }
        
        .notification.high {
            background: #f44336;
        }
        
        .notification.normal {
            background: #2196f3;
        }
        
        @keyframes slideIn {
            from {
                transform: translateX(100%);
                opacity: 0;
            }
            to {
                transform: translateX(0);
                opacity: 1;
            }
        }
    </style>
</head>
<body>
    <div id="connectionStatus" class="status disconnected">🔴 未连接</div>
    
    <div class="container">
        <div class="header">
            <h1>🚀 MCP 协议演示</h1>
            <p>Model Context Protocol - 工具、资源、提示的标准化交互</p>
        </div>
        
        <div class="main-content">
            <div class="tabs">
                <div class="tab active" onclick="showTab('capabilities')">📊 服务器能力</div>
                <div class="tab" onclick="showTab('tools')">🔧 工具调用</div>
                <div class="tab" onclick="showTab('resources')">📂 资源获取</div>
                <div class="tab" onclick="showTab('prompts')">💬 提示渲染</div>
            </div>
            
            <!-- 服务器能力展示 -->
            <div id="capabilities" class="tab-content active">
                <div class="card">
                    <h3>🎯 MCP 核心概念</h3>
                    <p><strong>工具 (Tools)</strong> - 模型控制：AI可以自主决定调用的功能</p>
                    <p><strong>资源 (Resources)</strong> - 应用控制：提供给AI的结构化数据流</p>
                    <p><strong>提示 (Prompts)</strong> - 用户控制：可重用的指令模板</p>
                </div>
                
                <div id="capabilitiesContent">
                    <p>正在加载服务器能力...</p>
                </div>
            </div>
            
            <!-- 工具调用 -->
            <div id="tools" class="tab-content">
                <div class="card">
                    <h3>🔧 工具调用演示</h3>
                    <p>工具是AI模型可以自主调用的功能。选择一个工具并设置参数来测试：</p>
                    
                    <div class="form-group">
                        <label for="toolSelect">选择工具：</label>
                        <select id="toolSelect" onchange="updateToolForm()">
                            <option value="">请选择工具...</option>
                        </select>
                    </div>
                    
                    <div id="toolParameters"></div>
                    
                    <button class="btn" onclick="callTool()">🚀 调用工具</button>
                    
                    <div id="toolResult"></div>
                </div>
            </div>
            
            <!-- 资源获取 -->
            <div id="resources" class="tab-content">
                <div class="card">
                    <h3>📂 资源获取演示</h3>
                    <p>资源提供结构化的数据流给AI模型。选择一个资源来获取数据：</p>
                    
                    <div class="form-group">
                        <label for="resourceSelect">选择资源：</label>
                        <select id="resourceSelect" onchange="updateResourceForm()">
                            <option value="">请选择资源...</option>
                        </select>
                    </div>
                    
                    <div id="resourceParameters"></div>
                    
                    <button class="btn" onclick="getResource()">📥 获取资源</button>
                    
                    <div id="resourceResult"></div>
                </div>
            </div>
            
            <!-- 提示渲染 -->
            <div id="prompts" class="tab-content">
                <div class="card">
                    <h3>💬 提示渲染演示</h3>
                    <p>提示是可重用的指令模板。选择一个提示并填写参数：</p>
                    
                    <div class="form-group">
                        <label for="promptSelect">选择提示：</label>
                        <select id="promptSelect" onchange="updatePromptForm()">
                            <option value="">请选择提示...</option>
                        </select>
                    </div>
                    
                    <div id="promptParameters"></div>
                    
                    <button class="btn" onclick="renderPrompt()">✨ 渲染提示</button>
                    
                    <div id="promptResult"></div>
                </div>
            </div>
        </div>
    </div>
    
    <div id="notifications" class="notifications"></div>
    
    <script>
        let capabilities = null;
        let websocket = null;
        
        // 页面加载时初始化
        document.addEventListener('DOMContentLoaded', function() {
            loadCapabilities();
            connectWebSocket();
        });
        
        // 标签页切换
        function showTab(tabName) {
            // 隐藏所有标签内容
            document.querySelectorAll('.tab-content').forEach(content => {
                content.classList.remove('active');
            });
            
            // 移除所有标签的active类
            document.querySelectorAll('.tab').forEach(tab => {
                tab.classList.remove('active');
            });
            
            // 显示选中的标签内容
            document.getElementById(tabName).classList.add('active');
            
            // 为选中的标签添加active类
            event.target.classList.add('active');
        }
        
        // 加载服务器能力
        async function loadCapabilities() {
            try {
                const response = await fetch('/capabilities');
                capabilities = await response.json();
                displayCapabilities();
                populateSelects();
            } catch (error) {
                console.error('加载能力失败:', error);
                document.getElementById('capabilitiesContent').innerHTML = 
                    '<div class="result error">❌ 无法连接到MCP服务器</div>';
            }
        }
        
        // 显示服务器能力
        function displayCapabilities() {
            if (!capabilities) return;
            
            let html = '<div class="capabilities-grid">';
            
            // 工具
            capabilities.tools.forEach(tool => {
                html += `
                    <div class="capability-card tool">
                        <div class="capability-title">${tool.name}</div>
                        <p><strong>描述:</strong> ${tool.description}</p>
                        <p><strong>控制层级:</strong> ${tool.control_level}</p>
                        <p><strong>参数:</strong></p>
                        <ul>
                `;
                tool.parameters.forEach(param => {
                    const required = param.required ? '✓' : '○';
                    const defaultVal = param.default ? ` (默认: ${param.default})` : '';
                    html += `<li>${required} ${param.name} (${param.type}): ${param.description}${defaultVal}</li>`;
                });
                html += '</ul></div>';
            });
            
            // 资源
            capabilities.resources.forEach(resource => {
                html += `
                    <div class="capability-card resource">
                        <div class="capability-title">${resource.name}</div>
                        <p><strong>描述:</strong> ${resource.description}</p>
                        <p><strong>类型:</strong> ${resource.type}</p>
                        <p><strong>URI:</strong> ${resource.uri}</p>
                        <p><strong>控制层级:</strong> ${resource.control_level}</p>
                `;
                if (resource.template_params) {
                    html += '<p><strong>模板参数:</strong></p><ul>';
                    Object.entries(resource.template_params).forEach(([key, value]) => {
                        html += `<li>${key}: ${value}</li>`;
                    });
                    html += '</ul>';
                }
                html += '</div>';
            });
            
            // 提示
            capabilities.prompts.forEach(prompt => {
                html += `
                    <div class="capability-card prompt">
                        <div class="capability-title">${prompt.name}</div>
                        <p><strong>描述:</strong> ${prompt.description}</p>
                        <p><strong>控制层级:</strong> ${prompt.control_level}</p>
                        <p><strong>参数:</strong></p>
                        <ul>
                `;
                prompt.parameters.forEach(param => {
                    const required = param.required ? '✓' : '○';
                    const defaultVal = param.default ? ` (默认: ${param.default})` : '';
                    html += `<li>${required} ${param.name} (${param.type}): ${param.description}${defaultVal}</li>`;
                });
                html += '</ul></div>';
            });
            
            html += '</div>';
            document.getElementById('capabilitiesContent').innerHTML = html;
        }
        
        // 填充选择器
        function populateSelects() {
            if (!capabilities) return;
            
            // 工具选择器
            const toolSelect = document.getElementById('toolSelect');
            toolSelect.innerHTML = '<option value="">请选择工具...</option>';
            capabilities.tools.forEach(tool => {
                toolSelect.innerHTML += `<option value="${tool.name}">${tool.name} - ${tool.description}</option>`;
            });
            
            // 资源选择器
            const resourceSelect = document.getElementById('resourceSelect');
            resourceSelect.innerHTML = '<option value="">请选择资源...</option>';
            capabilities.resources.forEach(resource => {
                resourceSelect.innerHTML += `<option value="${resource.name}">${resource.name} - ${resource.description}</option>`;
            });
            
            // 提示选择器
            const promptSelect = document.getElementById('promptSelect');
            promptSelect.innerHTML = '<option value="">请选择提示...</option>';
            capabilities.prompts.forEach(prompt => {
                promptSelect.innerHTML += `<option value="${prompt.name}">${prompt.name} - ${prompt.description}</option>`;
            });
        }
        
        // 更新工具参数表单
        function updateToolForm() {
            const toolName = document.getElementById('toolSelect').value;
            const container = document.getElementById('toolParameters');
            
            if (!toolName || !capabilities) {
                container.innerHTML = '';
                return;
            }
            
            const tool = capabilities.tools.find(t => t.name === toolName);
            if (!tool) return;
            
            let html = '';
            tool.parameters.forEach(param => {
                const required = param.required ? ' required' : '';
                const placeholder = param.default ? `默认值: ${param.default}` : '';
                
                if (param.type === 'string') {
                    html += `
                        <div class="form-group">
                            <label for="param_${param.name}">${param.name} ${param.required ? '*' : ''}:</label>
                            <input type="text" id="param_${param.name}" placeholder="${placeholder}"${required}>
                            <small>${param.description}</small>
                        </div>
                    `;
                } else if (param.type === 'integer') {
                    html += `
                        <div class="form-group">
                            <label for="param_${param.name}">${param.name} ${param.required ? '*' : ''}:</label>
                            <input type="number" id="param_${param.name}" placeholder="${placeholder}"${required}>
                            <small>${param.description}</small>
                        </div>
                    `;
                }
            });
            
            container.innerHTML = html;
        }
        
        // 更新资源参数表单
        function updateResourceForm() {
            const resourceName = document.getElementById('resourceSelect').value;
            const container = document.getElementById('resourceParameters');
            
            if (!resourceName || !capabilities) {
                container.innerHTML = '';
                return;
            }
            
            const resource = capabilities.resources.find(r => r.name === resourceName);
            if (!resource || !resource.template_params) {
                container.innerHTML = '';
                return;
            }
            
            let html = '';
            Object.entries(resource.template_params).forEach(([key, desc]) => {
                html += `
                    <div class="form-group">
                        <label for="rparam_${key}">${key}:</label>
                        <input type="text" id="rparam_${key}" placeholder="${desc}">
                    </div>
                `;
            });
            
            container.innerHTML = html;
        }
        
        // 更新提示参数表单
        function updatePromptForm() {
            const promptName = document.getElementById('promptSelect').value;
            const container = document.getElementById('promptParameters');
            
            if (!promptName || !capabilities) {
                container.innerHTML = '';
                return;
            }
            
            const prompt = capabilities.prompts.find(p => p.name === promptName);
            if (!prompt) return;
            
            let html = '';
            prompt.parameters.forEach(param => {
                const required = param.required ? ' required' : '';
                const placeholder = param.default ? `默认值: ${param.default}` : '';
                
                if (param.name === 'code') {
                    html += `
                        <div class="form-group">
                            <label for="pparam_${param.name}">${param.name} ${param.required ? '*' : ''}:</label>
                            <textarea id="pparam_${param.name}" rows="5" placeholder="${placeholder}"${required}></textarea>
                            <small>${param.description}</small>
                        </div>
                    `;
                } else {
                    html += `
                        <div class="form-group">
                            <label for="pparam_${param.name}">${param.name} ${param.required ? '*' : ''}:</label>
                            <input type="text" id="pparam_${param.name}" placeholder="${placeholder}"${required}>
                            <small>${param.description}</small>
                        </div>
                    `;
                }
            });
            
            container.innerHTML = html;
        }
        
        // 调用工具
        async function callTool() {
            const toolName = document.getElementById('toolSelect').value;
            if (!toolName) {
                showError('toolResult', '请选择一个工具');
                return;
            }
            
            const tool = capabilities.tools.find(t => t.name === toolName);
            const parameters = {};
            
            tool.parameters.forEach(param => {
                const element = document.getElementById(`param_${param.name}`);
                if (element && element.value) {
                    parameters[param.name] = param.type === 'integer' ? parseInt(element.value) : element.value;
                } else if (param.default) {
                    parameters[param.name] = param.default;
                }
            });
            
            try {
                const response = await fetch('/tools/call', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({
                        tool_name: toolName,
                        parameters: parameters
                    })
                });
                
                const result = await response.json();
                showResult('toolResult', result);
            } catch (error) {
                showError('toolResult', `调用失败: ${error.message}`);
            }
        }
        
        // 获取资源
        async function getResource() {
            const resourceName = document.getElementById('resourceSelect').value;
            if (!resourceName) {
                showError('resourceResult', '请选择一个资源');
                return;
            }
            
            const resource = capabilities.resources.find(r => r.name === resourceName);
            let uri = resource.uri;
            const parameters = {};
            
            if (resource.template_params) {
                Object.keys(resource.template_params).forEach(key => {
                    const element = document.getElementById(`rparam_${key}`);
                    if (element && element.value) {
                        parameters[key] = element.value;
                    }
                });
            }
            
            try {
                const response = await fetch('/resources/get', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({
                        uri: uri,
                        parameters: parameters
                    })
                });
                
                const result = await response.json();
                showResult('resourceResult', result);
            } catch (error) {
                showError('resourceResult', `获取失败: ${error.message}`);
            }
        }
        
        // 渲染提示
        async function renderPrompt() {
            const promptName = document.getElementById('promptSelect').value;
            if (!promptName) {
                showError('promptResult', '请选择一个提示');
                return;
            }
            
            const prompt = capabilities.prompts.find(p => p.name === promptName);
            const parameters = {};
            
            prompt.parameters.forEach(param => {
                const element = document.getElementById(`pparam_${param.name}`);
                if (element && element.value) {
                    parameters[param.name] = element.value;
                } else if (param.default) {
                    parameters[param.name] = param.default;
                }
            });
            
            try {
                const response = await fetch('/prompts/render', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({
                        name: promptName,
                        parameters: parameters
                    })
                });
                
                const result = await response.json();
                showResult('promptResult', result);
            } catch (error) {
                showError('promptResult', `渲染失败: ${error.message}`);
            }
        }
        
        // 显示结果
        function showResult(containerId, result) {
            const container = document.getElementById(containerId);
            container.innerHTML = `<div class="result">${JSON.stringify(result, null, 2)}</div>`;
        }
        
        // 显示错误
        function showError(containerId, message) {
            const container = document.getElementById(containerId);
            container.innerHTML = `<div class="result error">${message}</div>`;
        }
        
        // WebSocket连接
        function connectWebSocket() {
            const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
            const wsUrl = `${protocol}//${window.location.host}/ws`;
            
            websocket = new WebSocket(wsUrl);
            
            websocket.onopen = function() {
                document.getElementById('connectionStatus').innerHTML = '🟢 已连接';
                document.getElementById('connectionStatus').className = 'status connected';
            };
            
            websocket.onmessage = function(event) {
                const data = JSON.parse(event.data);
                handleWebSocketMessage(data);
            };
            
            websocket.onclose = function() {
                document.getElementById('connectionStatus').innerHTML = '🔴 未连接';
                document.getElementById('connectionStatus').className = 'status disconnected';
                
                // 5秒后重连
                setTimeout(connectWebSocket, 5000);
            };
            
            websocket.onerror = function(error) {
                console.error('WebSocket错误:', error);
            };
        }
        
        // 处理WebSocket消息
        function handleWebSocketMessage(data) {
            if (data.type === 'notification') {
                showNotification(data.data);
            }
        }
        
        // 显示通知
        function showNotification(notification) {
            const container = document.getElementById('notifications');
            const div = document.createElement('div');
            div.className = `notification ${notification.priority}`;
            div.innerHTML = `
                <strong>${notification.priority.toUpperCase()}</strong><br>
                ${notification.message}
            `;
            
            container.appendChild(div);
            
            // 5秒后自动移除
            setTimeout(() => {
                if (div.parentNode) {
                    div.parentNode.removeChild(div);
                }
            }, 5000);
        }
    </script>
</body>
</html> 